#!/usr/bin/python3

import sys
import os
import csv
import argparse
import struct 

parser = argparse.ArgumentParser()

# -b (-i) 用指定的bin文件生成img文件，-i 可省略使用默认值
# (-i) -d 将指定的img文件写入SD卡，-i 可省略使用默认值
# -b (-i) -d 用指定的bin文件生成img文件，并写入SD卡，-i 可省略使用默认值
parser.add_argument('-b', '--bin')  # bin文件
parser.add_argument('-d', '--dcd')    # dcd配置文件
parser.add_argument('-i', '--img', default = "load.img")  # img文件 默认为load.img
parser.add_argument('-w', '--write')  # 烧写磁盘

parser.add_argument('-a', '--addr', default = "0x87800000")    # bin文件链接时的基地址

args = parser.parse_args()

args.addr = int(args.addr, 16)

# args.bin不是None，则需要将bin文件封装成img
if args.bin is not None:
    if not os.path.exists(args.bin):
        print('bin file : %s is not exist' % args.bin)
    print('bin file : %s' % args.bin)
    #未输入dcd配置文件，则使用脚本文件夹下的默认dcd配置文件
    if args.dcd is None:
        args.dcd = os.path.join(os.path.split(os.path.realpath(sys.argv[0]))[0], "dcdConfig.csv")
        print('use default dcd config file : %s' % args.dcd)
    else:
        args.dcd = os.path.realpath(args.dcd)
        print('dcd config file : %s' % args.dcd)
        
    # 读取dcd文件，并生成dcdConfig结构
    with open(args.dcd, 'r') as f:
        csvReader = csv.reader(f)
        dcdConfig = list(csvReader)
        
    #建立镜像文件
    with open(args.img, 'wb') as f:
        #头部时1k空数据
        for i in range(0x400):
            f.write(struct.pack('<B', 0x00))
        
        #写入ivt
        f.write(struct.pack('<B', 0xD1))
        f.write(struct.pack('>H', 32))
        f.write(struct.pack('<B', 0x40))
        f.write(struct.pack('<I', args.addr))
        f.write(struct.pack('<I', 0x00000000))
        f.write(struct.pack('<I', args.addr - len(dcdConfig) * 8 - 8))
        f.write(struct.pack('<I', args.addr - len(dcdConfig) * 8 - 20))
        f.write(struct.pack('<I', args.addr - len(dcdConfig) * 8 - 52))
        f.write(struct.pack('<I', 0x00000000))
        f.write(struct.pack('<I', 0x00000000))

        #写入Boot Data
        f.write(struct.pack('<I', args.addr - len(dcdConfig) * 8 - 1076))
        f.write(struct.pack('<I', 1024 + 32 + 12 + (len(dcdConfig) * 8 + 8) + os.path.getsize(args.bin)))
        f.write(struct.pack('<I', 0x00000000))

        #写入DCD
            #dcd头
        f.write(struct.pack('<B', 0xD2))
        f.write(struct.pack('>H', len(dcdConfig) * 8 + 8))
        f.write(struct.pack('<B', 0x41))
            #dcd wrute头
        f.write(struct.pack('<B', 0xCC))
        f.write(struct.pack('>H', len(dcdConfig) * 8 + 4))
        f.write(struct.pack('<B', 0x04))
            #dcd wrute数据
        for d in dcdConfig:
            f.write(struct.pack('>I', int(d[0], 16)))
            f.write(struct.pack('>I', int(d[1], 16)))

        #写入bin
        with open(args.bin, 'rb') as b:
            while(True):
                raw = b.read(1024)
                if len(raw) == 0:
                    break
                else:
                    f.write(raw)
        
        print('generate %s finished!' % args.img)

if args.write is not None:
    if not os.path.exists(args.write):
        print('img file : %s is not exist' % args.write)
    os.system('sudo dd if=%s of=%s bs=512' % (args.img, args.write))
    print("write %s to %s finished!" % (args.img, str(args.write)))









